from google.appengine.ext import blobstore
from google.appengine.ext import db

from lib import cache


def EntityAsDict(entity):
  return dict((p, getattr(entity, p)) for p in entity.properties())


class Version(cache.Model):
  version = db.StringProperty(required=True)


class Race(cache.Model):
  name = db.StringProperty(required=True)


class Buildable(cache.Model):
  race = db.ReferenceProperty(required=True, reference_class=Race)
  version = db.ReferenceProperty(required=True, reference_class=Version)
  name = db.StringProperty(required=True)

  cost_supply = db.IntegerProperty(required=True, default=0)
  cost_minerals = db.IntegerProperty(required=True, default=0)
  cost_gas = db.IntegerProperty(required=True, default=0)

  build_seconds = db.FloatProperty(required=True)
  built_from = db.SelfReferenceProperty()
  requires = db.ListProperty(db.Key)

  provides_supply = db.IntegerProperty(required=True, default=0)

  armor = db.FloatProperty(required=True, default=0.0)
  hit_points = db.FloatProperty(required=True, default=0.0)
  shields = db.FloatProperty(required=True, default=0.0)

  ground_attack = db.FloatProperty(required=True, default=0.0)
  air_attack = db.FloatProperty(required=True, default=0.0)
  attack_cooldown_seconds = db.FloatProperty(required=True, default=0.0)

  speed = db.FloatProperty(required=True, default=0.0)
  range = db.FloatProperty(required=True, default=0.0)
  sight = db.FloatProperty(required=True, default=0.0)

  light = db.BooleanProperty(required=True, default=False)
  armored = db.BooleanProperty(required=True, default=False)
  biological = db.BooleanProperty(required=True, default=False)
  mechanical = db.BooleanProperty(required=True, default=False)
  psionic = db.BooleanProperty(required=True, default=False)
  massive = db.BooleanProperty(required=True, default=False)
  structure = db.BooleanProperty(required=True, default=False)
  worker = db.BooleanProperty(required=True, default=False)

  def AsDict(self):
    response = EntityAsDict(self)
    # TODO(flamingcow): Pass these back in some form.
    for key, value in response.items():
      if isinstance(value, db.Model) or isinstance(value, list):
        del response[key]
    return response


class Map(cache.Model):
  name = db.StringProperty(required=True)
  starting_minerals = db.IntegerProperty(required=True)
  starting_gas = db.IntegerProperty(required=True)


class StartingObject(cache.Model):
  map = db.ReferenceProperty(required=True, reference_class=Map)
  race = db.ReferenceProperty(required=True, reference_class=Race)
  buildable = db.ReferenceProperty(required=True, reference_class=Buildable)


class Base(cache.Model):
  map = db.ReferenceProperty(required=True, reference_class=Map)


class WorkerGroup(cache.Model):
  base = db.ReferenceProperty(required=True, reference_class=Base)
 
  max_workers = db.IntegerProperty(required=True)
  resource_return_time = db.FloatProperty(required=True)
  minerals_returned = db.IntegerProperty(required=True, default=0)
  gas_returned = db.IntegerProperty(required=True, default=0)


class Replay(cache.Model):
  blob = blobstore.BlobReferenceProperty(required=True)
  sha256 = db.StringProperty(required=True)


class Object(cache.Model):
  buildable = db.ReferenceProperty(required=True, reference_class=Buildable)


class EventType:
  GAME_START = 1
  BUILD_START = 2
  BUILD_COMPLETE = 3
  ASSIGN_WORKER = 4
  RESOURCE_RETURN = 5
  ERROR = 6


class Event(cache.Model):
  type = db.IntegerProperty(required=True)
  time = db.FloatProperty(required=True)
  current_supply = db.IntegerProperty(required=True)
  max_supply = db.IntegerProperty(required=True)
  minerals = db.IntegerProperty(required=True)
  gas = db.IntegerProperty(required=True)
  # not a reference, so we don't have to save the object first
  obj = None
  value = db.StringProperty()


class BatchTask(db.Model):
  complete = db.BooleanProperty(required=True, default=False)
  entities_processed = db.IntegerProperty(required=True, default=0)


class TaskResult(db.Model):
  batch_task = db.ReferenceProperty(required=True, reference_class=BatchTask)
  target = db.ReferenceProperty(collection_name='taskresult_target_set')
  result = db.StringProperty(required=True)
